package com.wngz.generate;

import cn.hutool.core.io.FileUtil;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;

/**
 * 代码生成器 - 使用类路径加载模板
 */
public class CodeGenerator {

    /**
     * 主方法 - 生成代码
     *
     * @param args 命令行参数
     */
    public static void main(String[] args) {
        try {
            // 1. 设置生成参数
            String packageName = "com.wngz.generate";
            String dataName = "用户评论";
            String dataKey = "userComment";
            String upperDataKey = "UserComment";

            // 2. 准备数据模型
            Map<String, Object> dataModel = new HashMap<>();
            dataModel.put("packageName", packageName);
            dataModel.put("dataName", dataName);
            dataModel.put("dataKey", dataKey);
            dataModel.put("upperDataKey", upperDataKey);

            // 3. 获取项目路径（多模块项目适用）
            String projectPath = System.getProperty("user.dir");
            String outputBasePath = projectPath + File.separator + "src" + File.separator + "main" + File.separator + "java";

            // 4. 生成各层代码
            generateController(outputBasePath, packageName, upperDataKey, dataModel);
            generateService(outputBasePath, packageName, upperDataKey, dataModel);
            generateServiceImpl(outputBasePath, packageName, upperDataKey, dataModel);
            generateModels(outputBasePath, packageName, upperDataKey, dataModel);

            System.out.println("代码生成完成！");
        } catch (Exception e) {
            System.err.println("代码生成失败: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 生成Controller
     */
    private static void generateController(String basePath, String packageName,
                                           String upperDataKey, Map<String, Object> dataModel)
            throws IOException, TemplateException {
        String outputPath = buildOutputPath(basePath, packageName, "controller", upperDataKey + "Controller.java");
        doGenerate("TemplateController.java.ftl", outputPath, dataModel);
        System.out.println("生成Controller: " + outputPath);
    }

    /**
     * 生成Service接口
     */
    private static void generateService(String basePath, String packageName,
                                        String upperDataKey, Map<String, Object> dataModel)
            throws IOException, TemplateException {
        String outputPath = buildOutputPath(basePath, packageName, "service", upperDataKey + "Service.java");
        doGenerate("TemplateService.java.ftl", outputPath, dataModel);
        System.out.println("生成Service接口: " + outputPath);
    }

    /**
     * 生成Service实现类
     */
    private static void generateServiceImpl(String basePath, String packageName,
                                            String upperDataKey, Map<String, Object> dataModel)
            throws IOException, TemplateException {
        String outputPath = buildOutputPath(basePath, packageName, "service/impl", upperDataKey + "ServiceImpl.java");
        doGenerate("TemplateServiceImpl.java.ftl", outputPath, dataModel);
        System.out.println("生成Service实现类: " + outputPath);
    }

    /**
     * 生成模型类（DTO/VO）
     */
    private static void generateModels(String basePath, String packageName,
                                       String upperDataKey, Map<String, Object> dataModel)
            throws IOException, TemplateException {
        // 生成DTOs
        String dtoPath = buildOutputPath(basePath, packageName, "model/dto", upperDataKey + "AddRequest.java");
        doGenerate("model/TemplateAddRequest.java.ftl", dtoPath, dataModel);

        dtoPath = buildOutputPath(basePath, packageName, "model/dto", upperDataKey + "QueryRequest.java");
        doGenerate("model/TemplateQueryRequest.java.ftl", dtoPath, dataModel);

        dtoPath = buildOutputPath(basePath, packageName, "model/dto", upperDataKey + "EditRequest.java");
        doGenerate("model/TemplateEditRequest.java.ftl", dtoPath, dataModel);

        dtoPath = buildOutputPath(basePath, packageName, "model/dto", upperDataKey + "UpdateRequest.java");
        doGenerate("model/TemplateUpdateRequest.java.ftl", dtoPath, dataModel);

        // 生成VO
        String voPath = buildOutputPath(basePath, packageName, "model/vo", upperDataKey + "VO.java");
        doGenerate("model/TemplateVO.java.ftl", voPath, dataModel);

        System.out.println("生成模型类完成");
    }

    /**
     * 构建输出路径
     */
    private static String buildOutputPath(String basePath, String packageName,
                                          String subPackage, String fileName) {
        return basePath + File.separator +
                packageName.replace('.', File.separatorChar) + File.separator +
                subPackage + File.separator + fileName;
    }

    /**
     * 执行代码生成
     *
     * @param templateName 模板文件名（resources/templates下的相对路径）
     * @param outputPath   输出文件路径
     * @param model        数据模型
     */
    public static void doGenerate(String templateName, String outputPath, Object model)
            throws IOException, TemplateException {
        // 1. 创建FreeMarker配置
        Configuration configuration = new Configuration(Configuration.VERSION_2_3_31);

        // 2. 设置从类路径加载模板
        configuration.setClassForTemplateLoading(CodeGenerator.class, "/templates");
        configuration.setDefaultEncoding("UTF-8");

        // 3. 获取模板
        Template template = configuration.getTemplate(templateName);

        // 4. 确保输出目录存在
        File outputFile = new File(outputPath);
        FileUtil.mkdir(outputFile.getParentFile());

        // 5. 生成文件
        try (Writer out = new FileWriter(outputFile)) {
            template.process(model, out);
        }
    }
}